package com.biboheart.brick.bit;

import lombok.Getter;

@Getter
public class BhBit<T extends Number> {
    private T value;

    /**
     * 构造函数
     */
    public BhBit() {
        this.value = null;
    }

    /**
     * 构造函数
     * @param value 数值
     */
    public BhBit(T value) {
        if (!(value instanceof Long || value instanceof Integer)) {
            throw new IllegalArgumentException("只支持Long或Integer类型");
        }
        this.value = value;
    }

    /**
     * 获取实例
     * @param value 数值
     * @return 实例
     */
    public static <T extends Number> BhBit<T> getInstance(T value) {
        if (null == value) {
            return new BhBit<>();
        }
        return new BhBit<>(value);
    }

    /**
     * 设置位值
     * @param index 二进制位下标
     * @param value 设置的值，0为假，大于0为真
     */
    @SuppressWarnings("unchecked")
    public BhBit<T> set(int index, boolean value) {
        if (null == this.value) {
            this.value = (T) Long.valueOf(0);
        }
        if (value) {
            if (this.value instanceof Integer) {
                this.value = (T) Integer.valueOf(this.value.intValue() | (1 << index));
            } else if (this.value instanceof Long) {
                this.value = (T) Long.valueOf(this.value.longValue() | (1L << index));
            }
        } else {
            if (this.value instanceof Integer) {
                this.value = (T) Integer.valueOf(this.value.intValue() & ~(1 << index));
            } else if (this.value instanceof Long) {
                this.value = (T) Long.valueOf(this.value.longValue() & ~(1L << index));
            }
        }
        return this;
    }

    /**
     * 设置位值
     * @param index 二进制位下标
     * @param value 设置的值，0为假，大于0为真
     * @return 实例
     */
    public BhBit<T> set(int index, int value) {
        return this.set(index, value > 0);
    }

    /**
     * 判断位值是否为指定值
     * @param index 二进制位下标
     * @param value 判断的值，0为假，大于0为真
     * @return 是否为真
     */
    public boolean is(int index, boolean value) {
        if (null == this.value) {
            return false;
        }
        if (this.value instanceof Integer) {
            if (value) {
                return (this.value.intValue() & (1 << index)) > 0;
            } else {
                return ((~this.value.intValue()) & 1 << index) > 0;
            }
        } else if (this.value instanceof Long) {
            if (value) {
                return (this.value.longValue() & (1L << index)) > 0;
            } else {
                return ((~this.value.longValue()) & 1L << index) > 0;
            }
        }
        return false;
    }

    /**
     * 判断位值是否为指定值
     * @param index 二进制位下标
     * @param value 判断的值，0为假，大于0为真
     * @return 是否为真
     */
    public boolean is(int index, int value) {
        return this.is(index, value > 0);
    }

    /**
     * 判断位值是否为真
     * @param index 二进制位下标
     * @return 是否为真
     */
    public boolean isTrue(int index) {
        return this.is(index, true);
    }

    /**
     * 判断位值是否为假
     * @param index 二进制位下标
     * @return 是否为假
     */
    public boolean isFalse(int index) {
        return this.is(index, false);
    }
}
